package com.micro.school.order.controller;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.micro.school.common.core.constant.CacheConstants;
import com.micro.school.common.core.constant.PayConstants;
import com.micro.school.common.core.context.SecurityContextHolder;
import com.micro.school.common.core.utils.SecurityContextHolderUtils;
import com.micro.school.common.core.utils.poi.ExcelUtil;
import com.micro.school.common.core.web.controller.BaseController;
import com.micro.school.common.core.web.domain.AjaxResult;
import com.micro.school.common.core.web.page.TableDataInfo;
import com.micro.school.common.log.annotation.Log;
import com.micro.school.common.log.enums.BusinessType;
import com.micro.school.common.redis.service.RedisService;
import com.micro.school.common.security.utils.SecurityUtils;
import com.micro.school.order.bo.GenerateBillBo;
import com.micro.school.order.bo.PayStandardFeeItemBo;
import com.micro.school.order.entity.PayFeeItemConfig;
import com.micro.school.order.entity.PayStandardFeeItem;
import com.micro.school.order.entity.PayStandardFeeItemDetail;
import com.micro.school.order.service.*;
import com.micro.school.order.vo.PayStandardFeeItemDetailVo;
import com.micro.school.order.vo.PayStandardFeeItemVo;
import com.micro.school.system.api.model.LoginUser;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * 标准收费项目管理Controller
 * 
 * @author lyb
 * @date 2025-08-14
 */
@RestController
@RequestMapping("/pay/payStandardFeeItem")
public class PayStandardFeeItemController extends BaseController
{
    @Autowired
    private IPayStandardFeeItemService payStandardFeeItemService;

    @Autowired
    private IPayFeeItemConfigService configService;

    @Autowired
    private IPayStandardFeeItemDetailService detailService;

    @Autowired
    private IPayStudentFeeService studentFeeService;

    private ThreadPoolTaskExecutor executor;

    @Autowired
    private RedisService redisService;

    @Autowired
    private ICollegeService  collegeService;

    /**
     * 查询标准收费项目管理列表
     */
    @GetMapping("/listHead")
    public AjaxResult listHead()
    {
        List<Map<String,String>> cols = new ArrayList<>();
//        Map<String,String> col1 = new HashMap<>();
//        col1.put("key","id");
//        col1.put("value","主键");
//        cols.add(col1);
//
//        Map<String,String> col2 = new HashMap<>();
//        col2.put("key","feeYear");
//        col2.put("value","收费学年");
//        cols.add(col2);
//
//        Map<String,String> col3 = new HashMap<>();
//        col3.put("key","modelName");
//        col3.put("value","模式");
//        cols.add(col3);
//
//        Map<String,String> col4 = new HashMap<>();
//        col4.put("key","modelName");
//        col4.put("value","模式");
//        cols.add(col4);
//
//
//        Map<String,String> col5 = new HashMap<>();
//        col5.put("key","majorName");
//        col5.put("value","专业");
//        cols.add(col5);
//
//        Map<String,String> col6 = new HashMap<>();
//        col6.put("key","studyPeriod");
//        col6.put("value","学制");
//        cols.add(col6);
//
//
//        Map<String,String> col7 = new HashMap<>();
//        col7.put("key","gradeName");
//        col7.put("value","年级");
//        cols.add(col7);

//        Map<String,String> col8 = new HashMap<>();
//        col8.put("key","totalAmount");
//        col8.put("value","总金额");
//        cols.add(col8);

        //添加动态字段
        addDaymicCol(cols);


//        Map<String,String> col9 = new HashMap<>();
//        col9.put("key","closeStatus");
//        col9.put("value","状态");
//        cols.add(col9);
//
//
//        Map<String,String> col10 = new HashMap<>();
//        col10.put("key","generateStatus");
//        col10.put("value","系统生成账单状态");
//        cols.add(col10);
//
//        Map<String,String> col11 = new HashMap<>();
//        col11.put("key","createTime");
//        col11.put("value","创建时间");
//        cols.add(col11);
        return AjaxResult.success(cols);
    }

    private void addDaymicCol(List<Map<String,String>> cols){
        List<PayFeeItemConfig> itemConfigs = getPayFeeItemConfig();
        if(null!=itemConfigs && !itemConfigs.isEmpty()){
            for(PayFeeItemConfig config:itemConfigs){
                Map<String,String> col = new HashMap<>();
                col.put("key","fee_"+config.getId().toString());
                col.put("value",config.getItemName());
                cols.add(col);
            }
        }
    }

    private List<PayFeeItemConfig> getPayFeeItemConfig(){
        LoginUser loginUser = SecurityUtils.getLoginUser();
        PayFeeItemConfig query = new PayFeeItemConfig();
//        if (!SecurityContextHolder.getUserName().contains("admin")) {
//            query.setCampusId(Integer.parseInt(SecurityContextHolder.getUserCompusId()));
//        }
        query.setTenantId(loginUser.getTenantId());
        List<PayFeeItemConfig> itemConfigs = configService.selectPayFeeItemConfigList(query);
        if(null!=itemConfigs && !itemConfigs.isEmpty()){
            // 过滤掉 openStatus == "N" 的记录，保留其余
            itemConfigs = itemConfigs.stream()
                    .filter(config -> PayConstants.CLOSESTATUS_1.equals(config.getCloseStatus()))
                    .collect(Collectors.toList());
            //按照getOrderNum生序排列
            itemConfigs.sort(Comparator.comparing(PayFeeItemConfig::getOrderNum));
        }
        return itemConfigs;
    }

    /**
     * 查询标准收费项目管理列表
     */
    @GetMapping("/list")
    public TableDataInfo list(PayStandardFeeItem payStandardFeeItem)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        payStandardFeeItem.setTenantId(loginUser.getTenantId());
//        payStandardFeeItem.setTenantId(Integer.valueOf(SecurityContextHolder.getUserTenantId()));
        if (!SecurityContextHolder.getUserName().contains("admin")) {
            payStandardFeeItem.setCampusIds(SecurityContextHolderUtils.getCampusId() != null && SecurityContextHolderUtils.getCampusId().length > 0 ? SecurityContextHolderUtils.getCampusId(): null);
            payStandardFeeItem.setCollegeIds(SecurityContextHolderUtils.getCollegeId() != null && SecurityContextHolderUtils.getCollegeId().length > 0 ? SecurityContextHolderUtils.getCollegeId(): null);
        }
        startPage();
        List<PayStandardFeeItemVo> list = payStandardFeeItemService.selectPayStandardFeeItemList(payStandardFeeItem);
        
        // 在数据转换前获取分页信息
        TableDataInfo tableDataInfo = getDataTable(list);
        
        List<JSONObject> result = new ArrayList<>();
        if(null!=list && !list.isEmpty()){
            for(PayStandardFeeItemVo item:list){
                PayStandardFeeItemDetail detailQuery = new PayStandardFeeItemDetail();
                detailQuery.setFeeItemId(item.getId());
                List<PayStandardFeeItemDetailVo> details = detailService.selectPayStandardFeeItemDetailList(detailQuery);
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(item));
                detailAdd(details,jsonObject);
                result.add(jsonObject);
            }
        }
        
        // 使用转换后的数据更新rows，但保持原有的total
        tableDataInfo.setRows(result);
        return tableDataInfo;
    }

    /***
     * 动态费用添加到记录
     * */
    private void detailAdd(List<PayStandardFeeItemDetailVo> details,JSONObject jsonObject){
        if(null==details || details.isEmpty()){
            return;
        }
        for(PayStandardFeeItemDetailVo detail:details){
            jsonObject.put("fee_"+detail.getFeeItemConfigId().toString(),detail.getItemPrice());
        }
    }

    /**
     * 导出标准收费项目管理列表
     */
    @Log(title = "标准收费项目管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, PayStandardFeeItem payStandardFeeItem)
    {
        List<PayStandardFeeItemVo> list = payStandardFeeItemService.selectPayStandardFeeItemList(payStandardFeeItem);
        ExcelUtil<PayStandardFeeItemVo> util = new ExcelUtil<PayStandardFeeItemVo>(PayStandardFeeItemVo.class);
        util.exportExcel(response, list, "标准收费项目管理数据");
    }

    /**
     * 获取标准收费项目管理详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        PayStandardFeeItemVo itemVo = payStandardFeeItemService.selectPayStandardFeeItemById(id);
        if(itemVo.getTenantId().intValue()!=loginUser.getSysUser().getTenantId().intValue()){
            return AjaxResult.error();
        }
        List<PayStandardFeeItemDetailVo> detailVos = detailService.selectPayStandardFeeItemDetailByFeeItemId(itemVo.getId());
        detailVos = detailVos.stream()
                .sorted(Comparator.comparing(
                        PayStandardFeeItemDetailVo::getOrderNum,
                        Comparator.nullsLast(Integer::compareTo)
                ))
                .collect(Collectors.toList());
        itemVo.setDetails(detailVos);
        return success(itemVo);
    }

    /**
     * 新增标准收费项目管理
     */
    @Log(title = "标准收费项目管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody PayStandardFeeItemBo feeItemBo)
    {
        if(null==feeItemBo.getDetails() || feeItemBo.getDetails().isEmpty()){
            return AjaxResult.error("明细费用不能为空");
        }
        feeItemBo.setCampusId(collegeService.getCampusIdByCollegeId(feeItemBo.getCollegeId()));
        feeItemBo.setTenantId(Integer.parseInt(SecurityContextHolder.getUserTenantId()));
        return payStandardFeeItemService.insertPayStandardFeeItem(feeItemBo);
    }

    /**
     * 修改标准收费项目管理
     */
    @Log(title = "标准收费项目管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody PayStandardFeeItemBo feeItemBo)
    {
        if(null==feeItemBo.getDetails() || feeItemBo.getDetails().isEmpty()){
            return AjaxResult.error("明细费用不能为空");
        }
        if(null==feeItemBo.getId()){
            return AjaxResult.error("id为空，不可以更新");
        }
        LoginUser loginUser = SecurityUtils.getLoginUser();
        PayStandardFeeItemVo itemQuery = payStandardFeeItemService.selectPayStandardFeeItemById(feeItemBo.getId());
        if(null==itemQuery){
            return AjaxResult.error("单据不存在");
        }
        //如果已经部分支付返回
        if(PayConstants.BILLSTATUS_10.equals(itemQuery.getGenerateStatus())){
            return AjaxResult.error("已生成对账单，不允许修改");
        }
        if(itemQuery.getTenantId().intValue()!=loginUser.getSysUser().getTenantId().intValue()){
            return AjaxResult.error("数据权限错误");
        }
        feeItemBo.setCampusId(collegeService.getCampusIdByCollegeId(feeItemBo.getCollegeId()));
        feeItemBo.setTenantId(loginUser.getSysUser().getTenantId().intValue());
        return payStandardFeeItemService.updatePayStandardFeeItem(feeItemBo);
    }


    /**
     * 打开
     */
    @PostMapping(value = "/open/{id}")
    public AjaxResult open(@PathVariable("id") Long id)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        PayStandardFeeItem item = new PayStandardFeeItem();
        item.setCloseStatus(PayConstants.CLOSESTATUS_1);
        item.setId(id);
        item.setTenantId(loginUser.getSysUser().getTenantId().intValue());
        item.setUpdateBy(loginUser.getUsername());
        item.setUpdateTime(new Date());
        return toAjax(payStandardFeeItemService.updatePayStandardFeeItem(item));
    }

    /**
     * 关闭
     */
    @PostMapping(value = "/close/{id}")
    public AjaxResult close(@PathVariable("id") Long id)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        PayStandardFeeItem item = new PayStandardFeeItem();
        item.setCloseStatus(PayConstants.CLOSESTATUS_2);
        item.setId(id);
        item.setTenantId(loginUser.getSysUser().getTenantId().intValue());
        item.setUpdateBy(loginUser.getUsername());
        item.setUpdateTime(new Date());
        return toAjax(payStandardFeeItemService.updatePayStandardFeeItem(item));
    }


    /**
     * 生成账单
     */
    @PostMapping(value = "/generateBill/{id}")
    public AjaxResult generateBill(@PathVariable("id") Long id)
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        PayStandardFeeItemVo itemQuery = payStandardFeeItemService.selectPayStandardFeeItemById(id);
        if(itemQuery.getTenantId().intValue() != loginUser.getSysUser().getTenantId().intValue()){
            return AjaxResult.error();
        }
        if(!itemQuery.getGenerateStatus().equals(PayConstants.GENERATESTATUS_2)){
            return AjaxResult.error("已经生成，不需要再次请求");
        }
        //已停用，不能生成账单
        if(null!=itemQuery.getCloseStatus() && itemQuery.getCloseStatus().equals(PayConstants.CLOSESTATUS_2)){
            return AjaxResult.error("已关闭，不能生成账单");
        }
        //更新收费标准记录账单生成中
        PayStandardFeeItem update = new PayStandardFeeItem();
        update.setId(itemQuery.getId());
        update.setGenerateStatus(PayConstants.GENERATESTATUS_3);
        update.setTenantId(loginUser.getSysUser().getTenantId().intValue());
        payStandardFeeItemService.updatePayStandardFeeItem(update);

        //异步生成账单，结束后修改状态
        if(null==executor){
            initThreadPool();
        }
        boolean lock = redisService.tryLock(CacheConstants.GENERATEBILL_LOCK+update.getId(),"1",1, TimeUnit.HOURS);
        if(lock){
            GenerateBillBo billBo = new GenerateBillBo();
            billBo.setFeeItemId(itemQuery.getId());
            billBo.setCreateTime(new Date());
            billBo.setCreateDept(loginUser.getSysUser().getDeptId());
            billBo.setCreateBy(loginUser.getUsername());
            billBo.setUpdateBy(loginUser.getUsername());
            billBo.setCreateTime(new Date());
            // 提交任务
            executor.execute(() -> {
                studentFeeService.generateBill(billBo);
            });
            return AjaxResult.success();
        }else {
            return AjaxResult.error("正在生成");
        }
    }

    private void initThreadPool(){
        synchronized (PayStandardFeeItemController.class){
            if(null==executor){
                executor = new ThreadPoolTaskExecutor();
                executor.setCorePoolSize(2);
                executor.setMaxPoolSize(5);
                executor.setQueueCapacity(1000);
                executor.setThreadNamePrefix("generate-bill-");
                executor.initialize();
            }
        }
    }
}
